package main

import (
	"fmt"
	"sync"
	"time"
)

// 定义一个结构体，用于演示对象复用
type Buffer struct {
	data []byte
}

func main() {
	// 创建一个sync.Pool
	// New字段定义了当Pool中没有可用对象时如何创建新对象
	bufferPool := &sync.Pool{
		New: func() interface{} {
			buffer := &Buffer{
				data: make([]byte, 1024), // 创建一个1KB的缓冲区
			}
			fmt.Println("创建新的Buffer")
			return buffer
		},
	}

	// 模拟多个goroutine并发使用Pool
	var wg sync.WaitGroup
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(id int) {
			defer wg.Done()

			// 从Pool获取一个对象
			buffer := bufferPool.Get().(*Buffer)

			// 使用完后，将对象放回Pool
			defer bufferPool.Put(buffer)

			// 模拟使用buffer进行一些操作
			fmt.Printf("Goroutine %d: 使用Buffer进行操作\n", id)

			// 填充一些数据
			for i := 0; i < 10; i++ {
				buffer.data[i] = byte(i)
			}

			// 打印前10个字节
			fmt.Printf("Goroutine %d: Buffer数据: %v\n", id, buffer.data[:10])

			// 模拟一些处理时间
			time.Sleep(100 * time.Millisecond)
		}(i)
	}

	// 等待所有goroutine完成
	wg.Wait()

	// 演示Pool的复用效果
	fmt.Println("\n演示对象复用:")

	// 获取一个对象
	buffer1 := bufferPool.Get().(*Buffer)
	fmt.Println("获取到buffer1")

	// 放回Pool
	bufferPool.Put(buffer1)
	fmt.Println("将buffer1放回Pool")

	// 再次获取，应该会得到刚才放回的对象
	buffer2 := bufferPool.Get().(*Buffer)
	fmt.Println("获取到buffer2 (应该是复用的buffer1)")

	// 比较两个对象的地址
	fmt.Printf("buffer1地址: %p\n", buffer1)
	fmt.Printf("buffer2地址: %p\n", buffer2)
	fmt.Printf("buffer1和buffer2是否是同一个对象: %v\n", buffer1 == buffer2)
}
